﻿using Core.Logger;
using Hardware.Reactor.Base;
using Hardware.Reactor.Base.Model;
using Hardware.Reactor.Base.Setting;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Hardware.Reactor.Default
{
    /// <summary>
    /// 电机控制：运动控制器，反应釜的搅拌电机、控制转速
    /// </summary>
    class MotionController : ReactiveObject, IMotionController
    {
        public MotionController() 
        {
            MessageObservable = this.WhenAnyValue(p => p.Message);
        }

        private SerialPort serialPort = null;
        private TcpClient tcpClient = null;
        private ConcurrentQueue<byte[]> receiveQueue = new ConcurrentQueue<byte[]>();
        private ConcurrentQueue<byte[]> sendQueue = new ConcurrentQueue<byte[]>();
        private IReactorConfigProvider provider = null;
        private CancellationTokenSource cts = new CancellationTokenSource();

        [Reactive]
        public bool Initialized { get; private set; }
        [Reactive]
        public bool Connected { get; private set; }
        [Reactive]
        public string Message { get; private set; }
        [Reactive]
        public IObservable<string> MessageObservable { get; private set; }

        public ConnectionMode ConnectionMode { get; private set; } = ConnectionMode.串口;

        public bool CheckConnection()
        {
            throw new NotImplementedException();
        }

        public void Close()
        {
            throw new NotImplementedException();
        }

        public bool Init(IReactorConfigProvider config, ConnectionMode connectionMode = ConnectionMode.串口)
        {
            this.provider = config;
            this.ConnectionMode = connectionMode;
            bool result = false;

            try
            {
                if (ConnectionMode == ConnectionMode.串口)
                {
                    if (serialPort == null)
                    {
                        serialPort = new SerialPort(config.ReactorConfig.MotionControllerPortName, config.ReactorConfig.MotionControllerBaudRate); ;
                        serialPort.Open();
                    }

                    if (serialPort.IsOpen)
                    {
                        Initialized = serialPort.IsOpen;
                    }

                    Connected = serialPort.IsOpen;


                }
                else
                {
                    if (tcpClient == null)
                    {
                        tcpClient = new TcpClient();
                        tcpClient.ConnectAsync(config.ReactorConfig.MotionControllerIP, config.ReactorConfig.MotionControllerPort).Wait(3000);
                    }

                    if (tcpClient.Connected)
                    {
                        Initialized = tcpClient.Connected;
                    }

                    Connected = tcpClient.Connected;

                }

                if (connectionMode == ConnectionMode.串口)
                {
                    //串口接收数据订阅回调函数
                    serialPort.DataReceived += (s, e) =>
                    {
                        Thread.Sleep(15);
                        int length = serialPort.BytesToRead;
                        byte[] buffer = new byte[length];
                        serialPort.Read(buffer, 0, length);//读取串口缓冲区的数据
                        receiveQueue.Enqueue(buffer);//入队
                    };
                }

                Task.Factory.StartNew(ReceiveTask);//TCP接收线程
                Task.Factory.StartNew(AnalysisTask);//处理数据
                Task.Factory.StartNew(ReadTask);//读取反应釜浊度
                Task.Factory.StartNew(SendTask);//下发指令线程
            }
            catch (Exception ex)
            {
                Logs.LogError(ex);
            }          

            return result;
        }
        /// <summary>
        /// 网口接收命名线程
        /// </summary>
        private void ReceiveTask()
        {
            while(!cts.Token.IsCancellationRequested)
            {
                try
                {
                    if (tcpClient == null) break;
                    if (!tcpClient.Connected)
                    {
                        Task.Delay(1000).Wait();
                        continue;
                    }
                    if (tcpClient.Available <= 0)
                    {
                        Task.Delay(2).Wait();
                        continue;
                    }
                    byte[] buffer = new byte[1024];//最大长度
                    int length = tcpClient.Client.Receive(buffer);//阻塞
                    byte[] receiveBytes = buffer.Take(length).ToArray();//实际长度
                    receiveQueue.Enqueue(receiveBytes);//入队
                }
                catch(Exception ex)
                {
                    Logs.LogError(ex);
                }
            }
        }

        /// <summary>
        /// 数据处理
        /// </summary>
        private void AnalysisTask()
        {
            while (!cts.Token.IsCancellationRequested)
            {
                var result = receiveQueue.TryDequeue(out var receive);
                if (result)
                {
                    DoAnalysis(receive);
                }
                else
                {
                    Task.Delay(2).Wait();
                }
            }
        }

        private void DoAnalysis(byte[] receive)
        {
            if(receive == null) return; 
            if(receive.Length > 0)
            {
                Message = $"[{DateTime.Now}]{Byte}";
            }
        }


        public bool Send(byte[] data)
        {
            throw new NotImplementedException();
        }

        public bool StartMachineMotor(MotorModel motor)
        {
            throw new NotImplementedException();
        }

        public bool StartMagneticMotor(MotorModel motor)
        {
            throw new NotImplementedException();
        }

        public bool StopMachineMotor(MotorModel motor)
        {
            throw new NotImplementedException();
        }

        public bool StopMagneticMotor(MotorModel motor)
        {
            throw new NotImplementedException();
        }
    }
}
